// derived from http://stackoverflow.com/questions/5357442/how-to-inspect-javascript-objects
function xinspect(obj,rdent) {
	var max_rdent = 12;
	var max_items = 20;
	var r = "";
	if( typeof rdent=='undefined' ) { rdent=" \t "; }
	var t=typeof obj;
	r += "("+t+") => ";
	if( 'object'==t ) {
		if( obj instanceof Array ) { r += "object/Array: "; }
		else { r += "object: "; }
		if( rdent.length > max_rdent ) {
			var c = 0; for(var p in obj){ c++; }
			r += ""+c+" keys [MAX DEPTH]\n";
		} else {
			var c = 0;
			var s = "";
			for(var p in obj) {
				c++;
				if( c < max_items ) {
					t = typeof obj[p];
					s += rdent+"\""+p+"\" "+xinspect( obj[p], rdent+" \t " );
				} else if( c == max_items ) { s += rdent+"[MAX ITEMS]\n"; }
			}
			r += ""+c+" keys\n"+s;
		}
	}
	else { r += ""+obj+"\n"; }
	return r;
}


// derived from http://stackoverflow.com/questions/950087/include-javascript-file-inside-javascript-file

function load_script( url, success, failure )
{
	//humane.log("Loading "+url+" with succes function "+success+" and failure function "+failure);
	// prepare script tag
	var script = document.createElement('script');
	script.type = 'text/javascript';
	script.src = url;
	// bind ready and error events to success and failure callbacks
	script.onreadystatechange = success;
	script.onload = success;
	script.onerror = failure;
	// add script to head, which triggers load of script
	var head = document.getElementsByTagName('head')[0];
	head.appendChild(script);
}
function load_scripts( url_list, success, timeout_ms, failure ) {
	var requested = url_list.length;
	var loaded = 0;
	var failed = 0;
	for( var i in url_list ) {
		var url = url_list[i];
		//see http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/
		var isucc=function(url){ return function() {
			loaded +=1;
			//humane.log( "loaded "+url+" ("+loaded+" of "+requested+")" );
			} }(url);
		var ifail=function(url){ return function() {
			failed +=1;
			humane.error( "Failed to load "+url+" ("+loaded+" of "+requested+")" );
			} }(url);
		load_script( url, isucc, ifail );
		//humane.log( "loading #"+i+": "+url );
	}
	wait_for_timeout( function(){return loaded>=requested;}, 1000, success, timeout_ms, failure );
	wait_for_timeout( function(){return failed>0;}, 1000, failure, timeout_ms );
}
function wait_for_timeout( condition, delay_ms, success, timeout_ms, failure )
{
	//humane.log( "wait_for_timeout:<br>codition="+condition+"<br>delay_ms="+delay_ms+"<br>success="+success+"<br>timeout_ms="+timeout_ms+"<br>failure="+failure );
	//humane.log( "wait_for_timeout:<br>codition="+condition+"<br>delay_ms="+delay_ms+"<br>timeout_ms="+timeout_ms );
	if( 'undefined' == typeof timeout_ms ) { timeout_ms = 60000; }
	if( 'undefined' == typeof failure ) { failure = function(){} }
	if( condition() ) { //condition met; invoke success callback
		//humane.log( "condition met<br>condition="+condition+"<br>success="+success );
		window.setTimeout( success, 0 );
	}
	else if( timeout_ms > 0 ) { //not met, not timed out; keep waiting
		//humane.log( "keep waiting<br>condition="+condition+"<br>delay_ms="+delay_ms+"<br>timeout_ms="+timeout_ms );
		window.setTimeout(
			function(){ wait_for_timeout(condition,delay_ms,success,timeout_ms-delay_ms,failure); },
			delay_ms
		);
	}
	else { //timed out, invoke failure callback
		//humane.log( "timed out<br>condition="+condition+"<br>failure="+failure );
		window.setTimeout( failure, 0 );
	}
}



function nothal_load(nothal,base)
{
	if( 'undefined' == typeof nothal.canvas ) { nothal.map = document.getElementById("nothal_map"); }
	//initialize canvas
	nothal.canvas = document.createElement('canvas');
	nothal.map.appendChild( nothal.canvas );
	if( 'undefined' == typeof nothal.selected ) { nothal.selected = document.getElementById("nothal_selected"); }
	if( 'undefined' == typeof nothal.countdisplay ) { nothal.countdisplay = document.getElementById("nothal_counter"); }
	if(typeof base=="undefined"){ base="."; }
	nothal.playing = [];
	nothal.gameloop = function() {
		crew_acts(nothal);
		nothal_redraw(nothal);
	}
	nothal.countdown = function() {
		if( 0 == --nothal.counter ) {
			playMusic( nothal, document.getElementById("loseMusic") );
			stop( nothal, "Too Slow!" );
		} else {
			if( nothal.dangertime == nothal.counter ) {
				playMusic( nothal, document.getElementById("dangerMusic") );
			}
			nothal.countdisplay.innerHTML = ""+nothal.counter;
		}
	}
	nothal.steptime = 500; //game loop interval in ms
	nothal.stopped = true;
	nothal.crewsize = 20;
	nothal.gametime = 100; //game time in ms
	nothal.dangertime = 20; //danger music starts here
	load_scripts(
		[ base+"/util.js", base+"/crew.js", base+"/wayfinder.js", base+"/UI.js",base+"/audio.js"],
		function() { //success function
			humane.log("Scripts Loaded");
			nothal.canvas.addEventListener(
				"click",
				function(evt) {
					var mousePos = getMousePos(nothal, evt);
					var density = is_passable(nothal,mousePos.x,mousePos.y);
					var densestr = density?" Passable ":" Solid ";
					var message = densestr+": " + mousePos.x + "," + mousePos.y;
					//humane.log(message);
				},
				false
			);
			load_tiles( function() {
				load_crew_sprites( function() {
					humane.log("Images Loaded");
					start();
					nothal_resize( nothal );
				} );
			} );
		},
		5000, //timeout
		function() { //failure function
			humane.error( "I'm sorry Dave," );
			window.setTimeout( function(){ humane.error( "I'm afraid I can't do that." ); }, 0 );
		}
	);
}


function nothal_resize(nothal)
{
	//console.log("nothal_resize");
	if( 'undefined' != typeof nothal.rooms ) {
		resize_canvas(nothal);
		nothal_redraw(nothal);
	}
	//console.log("resize complete")
}

function nothal_redraw(nothal) {
		render_maze(nothal);
		render_crew(nothal);
		nothal.update_selection();
}

function getMousePos(nothal, event)
{
	var rect = nothal.canvas.getBoundingClientRect();
	var x = unscale(event.clientX - rect.left,nothal.canvas.width);
	var y = unscale(event.clientY - rect.top, nothal.canvas.height);
	var radius = 1.5*(nothal.canvas.height+nothal.canvas.width)/200;
	for(var i=0; i<nothal.crew.length; i++)
	{
		var c = nothal.crew[i];
		if(Math.abs(x-c.x)<c.radius*1.5&&Math.abs(y-c.y)<c.radius*1.5)
		{
			nothal.selection = c;
			nothal.update_selection();
		}
	}

	var out = new Object();
	out.x = x;
	out.y = y;
	return out;

}


